package cn.fansunion.leecode.collection;

import java.util.ArrayList;
import java.util.List;

/**
 * 155. 最小栈 设计一个支持 push ，pop ，top 操作，并能在常数时间内检索到最小元素的栈。
 * 
 * push(x) —— 将元素 x 推入栈中。 pop() —— 删除栈顶的元素。 top() —— 获取栈顶元素。 getMin() —— 检索栈中的最小元素。
 * 
 * 来源：力扣（LeetCode） 链接：https://leetcode-cn.com/problems/min-stack 著作权归领扣网络所有。商业转载请联系官方授权，非商业转载请注明出处。
 * 
 * 思考：官方解法，看了，用2个栈，确实很妙；但是，感觉这样的解法有点无耻啊，充分利用题目的不确定性。
 * 很多题目描述的不够清楚，用2个栈去实现1个栈，这不是瞎折腾吗？实际工作中，有几个这样的需求。
 * @author wen.lei@brgroup.com
 *
 *         2022-2-18
 */
public class MinStack {
    private List<Integer> elementList = new ArrayList<>();
    private Integer min = null;

    /*示例:
    
        输入：
        ["MinStack","push","push","push","getMin","pop","top","getMin"]
        [[],[-2],[0],[-3],[],[],[],[]]
    
        输出：
        [null,null,null,null,-3,null,0,-2]
    
        解释：
        MinStack minStack = new MinStack();
        minStack.push(-2);
        minStack.push(0);
        minStack.push(-3);
        minStack.getMin();   --> 返回 -3.
        minStack.pop();
        minStack.top();      --> 返回 0.
        minStack.getMin();   --> 返回 -2.*/
    public MinStack() {

    }

    //每次push和pop时，更新min
    public void push(int val) {
        elementList.add(val);
        if(min!=null) {
            min = Math.min(min, val);
        }else {
            min=val;
        }
       
    }

    public void pop() {
        if (elementList.isEmpty()) {
            return;
        }
        Integer removed=elementList.remove(elementList.size() - 1);
        if(removed.equals(min)) {
            refreshMin();
        }
    }

    private void refreshMin() {
        min=min(elementList);
    }

    private Integer min(List<Integer> elementList) {
        if(elementList==null||elementList.size()==0) {
            return null;
        }
        Integer min=elementList.get(0);
        for(Integer num:elementList) {
            min=Math.min(min, num);
        }
        return min;
    }

    public int top() {
        if (elementList.isEmpty()) {
            throw new IllegalArgumentException("no element");
        }
        return elementList.get(elementList.size() - 1);
    }

    public int getMin() {
        return min;

    }

    /**
     * Your MinStack object will be instantiated and called as such: MinStack obj = new MinStack(); obj.push(val);
     * obj.pop(); int param_3 = obj.top(); int param_4 = obj.getMin();
     */
}
